bitkeeper revision 1.1159.275.1 (4244b7056FS2uC4AapFJtHCNgoKPFg)
authorcl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Sat, 26 Mar 2005 01:12:37 +0000 (01:12 +0000)
committercl349@firebug.cl.cam.ac.uk <cl349@firebug.cl.cam.ac.uk>
Sat, 26 Mar 2005 01:12:37 +0000 (01:12 +0000)
No direct entry to __enter_scheduler allowed. Must always pass through
softirq handler. Also domain_crash() now returns and defers
descheduling from local CPU: old behaviour is still provided by
domain_crash_synchronous().
Signed-off-by: Keir Fraser <keir@xensource.com>
Signed-off-by: Christian Limpach <Christian.Limpach@cl.cam.ac.uk>
xen/arch/x86/domain.c
xen/arch/x86/memory.c
xen/arch/x86/shadow.c
xen/arch/x86/traps.c
xen/arch/x86/x86_32/entry.S
xen/common/domain.c
xen/common/schedule.c
xen/include/xen/sched.h

index 812d14c5062ad185447a48e6b0451774cfeb0165..d47910233aceec93daed0767069199a662bd77b5 100644 (file)
@@ -82,7 +82,8 @@ void startup_cpu_idle_loop(void)
     /* Just some sanity to ensure that the scheduler is set up okay. */
     ASSERT(current->id == IDLE_DOMAIN_ID);
     domain_unpause_by_systemcontroller(current);
-    __enter_scheduler();
+    raise_softirq(SCHEDULE_SOFTIRQ);
+    do_softirq();
 
     /*
      * Declares CPU setup done to the boot processor.
index 6fb64a31fa80a695063380881c60bc3a4e27962d..4c91d7374bb78f611a58a779979c9db8ba271701 100644 (file)
@@ -1686,7 +1686,7 @@ void ptwr_flush(const int which)
         MEM_LOG("ptwr: Could not read pte at %p\n", ptep);
         /*
          * Really a bug. We could read this PTE during the initial fault,
-         * and pagetables can't have changed meantime. XXX Multi-CPU guests?
+         * and pagetables can't have changed meantime.
          */
         BUG();
     }
@@ -1713,7 +1713,7 @@ void ptwr_flush(const int which)
         MEM_LOG("ptwr: Could not update pte at %p\n", ptep);
         /*
          * Really a bug. We could write this PTE during the initial fault,
-         * and pagetables can't have changed meantime. XXX Multi-CPU guests?
+         * and pagetables can't have changed meantime.
          */
         BUG();
     }
@@ -1771,6 +1771,7 @@ void ptwr_flush(const int which)
                 *pl2e = mk_l2_pgentry(l2_pgentry_val(*pl2e) | _PAGE_PRESENT); 
             }
             domain_crash();
+            return;
         }
         
         if ( unlikely(sl1e != NULL) )
@@ -1834,13 +1835,17 @@ int ptwr_do_page_fault(unsigned long addr)
     /* Get the L2 index at which this L1 p.t. is always mapped. */
     l2_idx = page->u.inuse.type_info & PGT_va_mask;
     if ( unlikely(l2_idx >= PGT_va_unknown) )
+    {
         domain_crash(); /* Urk! This L1 is mapped in multiple L2 slots! */
+        return 0;
+    }
     l2_idx >>= PGT_va_shift;
 
     if ( l2_idx == (addr >> L2_PAGETABLE_SHIFT) )
     {
         MEM_LOG("PTWR failure! Pagetable maps itself at %08lx\n", addr);
         domain_crash();
+        return 0;
     }
 
     /*
@@ -1908,6 +1913,7 @@ int ptwr_do_page_fault(unsigned long addr)
         unmap_domain_mem(ptwr_info[cpu].ptinfo[which].pl1e);
         ptwr_info[cpu].ptinfo[which].l1va = 0;
         domain_crash();
+        return 0;
     }
     
     return EXCRET_fault_fixed;
@@ -1938,40 +1944,6 @@ __initcall(ptwr_init);
 
 #ifndef NDEBUG
 
-void ptwr_status(void)
-{
-    unsigned long pte, *ptep, pfn;
-    struct pfn_info *page;
-    int cpu = smp_processor_id();
-
-    ptep = (unsigned long *)&linear_pg_table
-        [ptwr_info[cpu].ptinfo[PTWR_PT_INACTIVE].l1va>>PAGE_SHIFT];
-
-    if ( __get_user(pte, ptep) ) {
-        MEM_LOG("ptwr: Could not read pte at %p\n", ptep);
-        domain_crash();
-    }
-
-    pfn = pte >> PAGE_SHIFT;
-    page = &frame_table[pfn];
-    printk("need to alloc l1 page %p\n", page);
-    /* make pt page writable */
-    printk("need to make read-only l1-page at %p is %08lx\n",
-           ptep, pte);
-
-    if ( ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va == 0 )
-        return;
-
-    if ( __get_user(pte, (unsigned long *)
-                    ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va) ) {
-        MEM_LOG("ptwr: Could not read pte at %p\n", (unsigned long *)
-                ptwr_info[cpu].ptinfo[PTWR_PT_ACTIVE].l1va);
-        domain_crash();
-    }
-    pfn = pte >> PAGE_SHIFT;
-    page = &frame_table[pfn];
-}
-
 void audit_domain(struct domain *d)
 {
     int ttot=0, ctot=0, io_mappings=0, lowmem_mappings=0;
index 01d67d43ad25a86f2725a0666b9ea8a41732ce49..465563fb8feaf9982a8465a56ed534845aab1e4b 100644 (file)
@@ -580,15 +580,13 @@ int shadow_fault(unsigned long va, long error_code)
                              &linear_pg_table[va >> PAGE_SHIFT])) )
     {
         SH_VVLOG("shadow_fault - EXIT: read gpte faulted" );
-        shadow_unlock(m);
-        return 0;
+        goto fail;
     }
 
     if ( unlikely(!(gpte & _PAGE_PRESENT)) )
     {
         SH_VVLOG("shadow_fault - EXIT: gpte not present (%lx)",gpte );
-        shadow_unlock(m);
-        return 0;
+        goto fail;
     }
 
     /* Write fault? */
@@ -598,8 +596,7 @@ int shadow_fault(unsigned long va, long error_code)
         {
             /* Write fault on a read-only mapping. */
             SH_VVLOG("shadow_fault - EXIT: wr fault on RO page (%lx)", gpte);
-            shadow_unlock(m);
-            return 0;
+            goto fail;
         }
 
         l1pte_write_fault(m, &gpte, &spte);
@@ -616,7 +613,10 @@ int shadow_fault(unsigned long va, long error_code)
     /* XXX Watch out for read-only L2 entries! (not used in Linux). */
     if ( unlikely(__put_user(gpte, (unsigned long *)
                              &linear_pg_table[va >> PAGE_SHIFT])) )
+    {
         domain_crash();
+        goto fail;
+    }
 
     /*
      * Update of shadow PTE can fail because the L1 p.t. is not shadowed,
@@ -637,6 +637,10 @@ int shadow_fault(unsigned long va, long error_code)
 
     check_pagetable(m, current->mm.pagetable, "post-sf");
     return EXCRET_fault_fixed;
+
+ fail:
+    shadow_unlock(m);
+    return 0;
 }
 
 
index 8e965c5f60d2ae4dae1cbbc3bc791e0b5ab962cb..df68d420fc9b27bc7e2f1a65162ad52f28780a05 100644 (file)
@@ -654,8 +654,6 @@ asmlinkage int do_debug(struct xen_regs *regs)
     struct domain *d = current;
     struct trap_bounce *tb = &d->thread.trap_bounce;
 
-    DEBUGGER_trap_entry(TRAP_debug, regs);
-
     __asm__ __volatile__("movl %%db6,%0" : "=r" (condition));
 
     /* Mask out spurious debug traps due to lazy DR7 setting */
@@ -666,6 +664,8 @@ asmlinkage int do_debug(struct xen_regs *regs)
         goto out;
     }
 
+    DEBUGGER_trap_entry(TRAP_debug, regs);
+
     if ( !GUEST_FAULT(regs) )
     {
         /* Clear TF just for absolute sanity. */
index aaf6caccef90920574f12c8da0000ee82160f3c0..b1559383106d772980facf3b9ca22a43de494be0 100644 (file)
@@ -112,7 +112,7 @@ DBLFLT1:GET_CURRENT(%ebx)
         jmp   test_all_events
 DBLFIX1:GET_CURRENT(%ebx)
         testb $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
-        jnz   domain_crash             # cannot reenter failsafe code
+        jnz   domain_crash_synchronous # cannot reenter failsafe code
         orb   $TF_failsafe_return,DOMAIN_thread_flags(%ebx)
         jmp   test_all_events          # will return via failsafe code
 .previous
@@ -330,7 +330,7 @@ DBLFLT2:jmp   process_guest_exception_and_events
        .long FLT23,FIX7 , FLT24,FIX7 , FLT25,FIX7 , FLT26,FIX7 , FLT27,FIX7
 .previous
 .section __ex_table,"a"
-        .long DBLFLT2,domain_crash
+        .long DBLFLT2,domain_crash_synchronous
 .previous
 
         ALIGN
@@ -620,9 +620,9 @@ VFLT3:  movl %gs:(%esi),%eax
         jmp test_all_events
 
 .section __ex_table,"a"
-        .long VFLT1,domain_crash
-        .long VFLT2,domain_crash
-        .long VFLT3,domain_crash
+        .long VFLT1,domain_crash_synchronous
+        .long VFLT2,domain_crash_synchronous
+        .long VFLT3,domain_crash_synchronous
 .previous
 
 .data
index 30b0677fbb06156e87de44afccf7df55e712839e..90e893899a82da5c2c6d23b2ca6be87794741df9 100644 (file)
@@ -9,6 +9,7 @@
 #include <xen/lib.h>
 #include <xen/errno.h>
 #include <xen/sched.h>
+#include <xen/softirq.h>
 #include <xen/mm.h>
 #include <xen/event.h>
 #include <xen/time.h>
@@ -146,8 +147,15 @@ void domain_crash(void)
 
     send_guest_virq(dom0, VIRQ_DOM_EXC);
     
-    __enter_scheduler();
-    BUG();
+    raise_softirq(SCHEDULE_SOFTIRQ);
+}
+
+
+void domain_crash_synchronous(void)
+{
+    domain_crash();
+    for ( ; ; )
+        do_softirq();
 }
 
 void domain_shutdown(u8 reason)
@@ -169,18 +177,14 @@ void domain_shutdown(u8 reason)
         }
     }
 
-    if ( reason == SHUTDOWN_crash )
-    {
-        domain_crash();
-        BUG();
-    }
-
-    current->shutdown_code = reason;
-    set_bit(DF_SHUTDOWN, &current->flags);
+    if ( (current->shutdown_code = reason) == SHUTDOWN_crash )
+        set_bit(DF_CRASHED, &current->flags);
+    else
+        set_bit(DF_SHUTDOWN, &current->flags);
 
     send_guest_virq(dom0, VIRQ_DOM_EXC);
 
-    __enter_scheduler();
+    raise_softirq(SCHEDULE_SOFTIRQ);
 }
 
 unsigned int alloc_new_dom_mem(struct domain *d, unsigned int kbytes)
index d16c2192f4dc8ffe8860fec5b3849283cfb235d5..9756b1851281774096b539c48ad7e5974b4e52cc 100644 (file)
@@ -79,7 +79,8 @@ static struct scheduler *schedulers[] = {
     NULL
 };
 
-/* Operations for the current scheduler. */
+static void __enter_scheduler(void);
+
 static struct scheduler ops;
 
 #define SCHED_OP(fn, ...)                                 \
@@ -310,7 +311,7 @@ long sched_adjdom(struct sched_adjdom_cmd *cmd)
  * - deschedule the current domain (scheduler independent).
  * - pick a new domain (scheduler dependent).
  */
-void __enter_scheduler(void)
+static void __enter_scheduler(void)
 {
     struct domain *prev = current, *next = NULL;
     int                 cpu = prev->processor;
index 254169cd9ffe06a26275764be4ff2b022f852d4e..8f5345375bf7e241aa2f81f35e3d723beb3db014 100644 (file)
@@ -184,9 +184,20 @@ struct domain *find_domain_by_id(domid_t dom);
 struct domain *find_last_domain(void);
 extern void domain_destruct(struct domain *d);
 extern void domain_kill(struct domain *d);
-extern void domain_crash(void);
 extern void domain_shutdown(u8 reason);
 
+/*
+ * Mark current domain as crashed. This function returns: the domain is not
+ * synchronously descheduled from any processor.
+ */
+extern void domain_crash(void);
+
+/*
+ * Mark current domain as crashed and synchronously deschedule from the local
+ * processor. This function never returns.
+ */
+extern void domain_crash_synchronous(void) __attribute__((noreturn));
+
 void new_thread(struct domain *d,
                 unsigned long start_pc,
                 unsigned long start_stack,
@@ -207,8 +218,6 @@ void init_idle_task(void);
 void domain_wake(struct domain *d);
 void domain_sleep(struct domain *d);
 
-void __enter_scheduler(void);
-
 extern void switch_to(struct domain *prev, 
                       struct domain *next);